#!/usr/bin/env python
# -*-coding: utf-8 -*-
# Filename: API_ghhp.py

#from sqlobject import *
# Modulo msj_retroalimentacion.py 
#from datetime import datetime
#####################
# CLASE InicioSesion
#####################
class MensajeInicioSesion:
    """
        Esta clase es la que va a permitir ejecuar el msj_inicio_sesion.
        Dependiendo del usuario, es la interfaz que se va a mostrar: 
            1. Interfaz Mesa de Ayuda.
            2. Interfaz Grupo de Resolucion.
            3. Interfaz Gerencia.
    """
    def __init__(self):
        """Setea las variables de instancia"""

    def conect_entry_enter(self):
        """Permite generar the activate signal para los widget.
        
        Permite navegar por los widget con el botón <Enter>. Luego de poner el
        nombre de usuario al presionar <Enter> salta al campo de contraseña y
        luego al botón aceptar"""

    def run():
        """Ejecuta el mensaje de retroalimentacion"""

    def verificar():
        """
        Obtiene el nombre de usuario y el password del usuario y realiza una
        consulta a la BD para consultar si el usuario existe.
        De ser asi le pregunta a que grupo pertenece para devolver ese valor. 
       
        >>> from lib.database import Usuario
        >>> opciones = {'MesaDeAyuda':1, 'GrupoDeResolucion':2, 'Gerencia':3}
        >>> try:
        ...     resultado = Usuario.selectBy(u_legajo = user, password = pass)[0]
        ... except IndexError, error:
        ...     return -1, None
        ...
        >>> opcion = resultado.grupo_de_resolucion.nombre
        >>> return opciones[opcion],resultado

        """
########################
# CLASE MensajeDeError
########################
class MensajeDeError:
    """
    Mensaje de retroalimentacion de Error.
    """
    def __init__(self, texto, padre=None):
        """
        @param texto: Texto mostrado en el mensaje de error
        @param padre: Widget padre del dialogo de error
        @type texto: C{string}
        @type padre: C{gtk.Window}
        """
    def run(self):
        """
        Corre el mensaje
        """
############################
# CLASE MensajeDeAdvertencia:
############################
class MensajeDeAdvertencia:
    """
    Mensaje de retroalimentacion de advertencia.
    """
    def __init__(self, texto, padre=None):
        """
        @param texto: Texto mostrado en el mensaje de error
        @param padre: Widget padre del dialogo de error
        @type texto: C{string}
        @type padre: C{gtk.Window}
        """
############################
# CLASE MensajeDeAbout:
############################
class MensajeDeAbout:
    """
    Mensade retroalimentacion de Acerca de....
    @require: la funcion {obtener_gpl}
    """
    def __init__(self, padre=None):
        """
        @param padre: Widget padre del dialogo de error
        @type padre: C{gtk.Window}
        """
    def obtener_gpl(self):
        """
        Setea la licencia C{GPL} en la solapa correspondiente a licencia del
        mensaje creado con esta clase.
         
        """
# Modulo database.py
#################
# Clase Empleado:
#################
class Empleado:
    """
    Encargada de gestionar los objetos empleados del sistema.
    """
    def __init__(self, nombre, apellido, legajo, e_mail, telefono_interno="",
            telefono_externo="", direcciones=None, historial_de_estado=None,
            usuarios=None, ticket=None):
        """
            >>> empleado = Empleado(nombre='Juan', apellido='Gimenenez',
            ...     legajo='33233', e_mail='jgimenez@gmail.com', usuario=None)
            >>> empleado.nombre
            u'Juan'
            >>> empleado.apellido
            u'Gimenenez'
            >>> empleado.direcciones
            []
            >>> empleado.tickets_reclamados
            []
            >>> empleado.usuario
            >>>

            @param nombre: Nombre del empleado
            @param apellido: Apellido del empleado
            @param legajo: Legajo del empleado
            @param e_mail: e_mail del empleado
            @param telefono_interno: NN
            @param telefono_externo: NN
            @param direcciones: direcciones
            @param historial_de_estado: NN
            @param usuarios: Nombre de usuario para el empleado si asi fuese.
            @param ticket: reclamos abiertos por el empleado.

            @type nombre: C{Unicode}
            @type apellido: C{Unicode}
            @type legajo: C{unicode}
            @type e_mail: C{unicode}
            @type telefono_interno: C{unicode}
            @type telefono_externo: C{unicode}
            @type direcciones: C{lib.database.Direccion}
            @type historial_de_estado: C{lib.database.HistorialDeEstado}
            @type usuarios: C{lib.database.Usuario}
            @type ticket: C{lib.database.Ticket}
        """
# Direccion
class Direccion:
    """
    Encargada de gestionar las direcciones del empleado.
    """
    def __init__(self, domicilio, numero, piso="", empleado=None):
        """
            >>> from lib.database import Direccion
            >>> direccion = Direccion(domicilio='Uruguay', numero = '165',
                            piso='1', empleado=empleado)
            >>> empleado.direcciones
            [<Direccion 2L domicilio=u'Uruguay' numero=u'165' piso=u'1' empleado_id=41L>]
            >>>

            @param domicilio: Domicilio del empleado
            @param numero: Numero del domicilio
            @param piso: Piso del domicilio
            @param empleado: Empleado al que le corresponde ese domicilio

            @type domicilio: C{unicode}
            @type numero: C{unicode}
            @type piso: C{unicode}
            @type empleado: C{lib.database.Empleado}

        """
class Usuario:
    """
    Encargada de gestionar los usuarios del sistema.
    """
    def __init__(self, u_legajo, password, descripcion_cargo, empleado,
            grupo_de_resolucion):
        """
        >>> usuario = Usuario(u_legajo='u56581',
        ...                     password='855941',
        ...                     descripcion_cargo='',
        ...                     empleado=empleado,
        ...                     grupo_de_resolucion=grupo)
        >>> usuario
        <Usuario 49 u_legajo=u'u56581' password=u'855941' descripcion_cargo=u''
            empleadoID=22L grupo_de_resolucionID=21L>
        Si queremos saber a que empleado pertenece este usuario:
        >>> usuario.empleado
        <Empleado 22 nombre=u'Tanya' apellido=u'Lichtenstein' legajo=u'56581'
            e_mail=u'aggus@live.com.ar' telefono_interno=u'' telefono_externo=u''
            usuarioID=49L>
        >>> usuario.empleado.nombre
        u'Tanya'
        >>> usuario.empleado.apellido
        u'Lichtenstein'
        Si queremos saber a que grupo pertenecemos:
        >>> usuario.grupo_de_resolucion
        <GrupoDeResolucion 21 estado=True fecha_creacion='datetime.datetime...)'
            descripcion=u'Te la encargo' nombre=u'pepe'>
        Si necesitamos los tickets que creo ó cerro este usuario hacemos:
        >>> usuario.tickets_creados
        []
        >>> usuario.tickets_cerrados
        []
        >>>

        @param u_legajo: nombre del usuario 'u + legajo empleado'
        @param password: password del usuario
        @param descripcion_cargo: descripcion de lo que hace el usuario
        @param empleado_id: id del empleado que pertenece al usuario
        @param grupo_de_resolucion_id: grupo al que pertenece el usuario

        @type u_legajo: C{unicode}
        @type password: C{unicode}
        @type descripcion_cargo: C{unicode}
        @type empleado_id: C{long}
        @type grupo_de_resolucion_id: C{long}

        """


class GrupoDeResolucion:
    """Son los grupos que resolveran las distintas problematicas del sistema.
    """
    def __init__(fecha_creacion, descripcion, nombre):
        """
        >>> grupo = GrupoDeResolucion(fecha_creacion=fecha,
        ...             descripcion='Descripcion del alcance del grupo',
        ...             nombre='Grupo de Resolucion Uno')
        >>> grupo
        <GrupoDeResolucion 22L estado=True fecha_creacion='datetime.datetime...)'
            descripcion="u'Descripcion del...'" nombre="u'Grupo de Resolu...'">
        >>>

        @param fecha_creacion: fecha de creacion del grupo.
        @param descripcion: descripcion del alcance del nuevo grupo.
        @param nombre: nombre identificatorio del nuevo grupo.

        @type fecha_creacion: C{datetime}
        @type descripcion: C{unicode}
        @type nombre: C{nombre}
        """
    def actualizar_estado_intervencion(self, intervencion, estado, fecha):
        """Modifica el estado de la intervencion, llamando a la funcion
        C{actualizar_estado_de_la_intervencion}, de la clase C{Intervencion}.

        >>> estado = 'Resuelta'
        >>> fecha = datetime.now()
        >>> grupo.intervenciones[9]
        <Intervencion 21 estado=u'Trabajando' fecha='datetime.datetime...)' clasificacionID=2L
            grupo_de_resolucionID=2L ticketID=10L>
        >>> grupo.actualizar_estado_intervencion(grupo.intervenciones[9], estado, fecha)
        >>> grupo.intervenciones[9]
        <Intervencion 21 estado=u'Resuelta' fecha='datetime.datetime...)' clasificacionID=2L
            grupo_de_resolucionID=2L ticketID=10L>
        >>>

        @param intervencion: intervencion que se quiere actualizar el estado.
        @param estado: nuevo estado de la intervencion.
        @param fecha: fecha del cambio de estado.

        @type intervencion: C{lib.database.Intervencion}
        @type estado: C{unicode}
        @type fecha: C{datetime}
        """

    def agregar_observacion(self, intervencion, descripcion, usuario, fecha,
            grupo):
        """Agrega observaciones, llamando a la funcion C{agregar_observaciones}
        de la clase C{Intervencion}.

        >>> descriocion = 'La intervencion esta siendo intervenida'
        >>> intervencion
            <Intervencion 10 estado=u'Finalizada' fecha='datetime.datetime...)'
            clasificacionID=1L grupo_de_resolucionID=2L ticketID=6L>
        >>> intervencion.observaciones
            [<Observacion 8 descripcion="u'que paso con el...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=4L fecha='datetime.datetime...)'>,
             <Observacion 9 descripcion="u'Necesitamos la ...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=4L fecha='datetime.datetime...)'>,
             <Observacion 13 descripcion="u'Lo volvemos a l...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=1L fecha='datetime.datetime...)'>]
        >>> len(intervencion.observaciones)
        3
        >>> grupo.agregar_observacion(intervencion, descripcion, usuario, fecha, grupo)
        >>> intervencion.observaciones
            [<Observacion 8 descripcion="u'que paso con el...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=4L fecha='datetime.datetime...)'>,
             <Observacion 9 descripcion="u'Necesitamos la ...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=4L fecha='datetime.datetime...)'>,
             <Observacion 13 descripcion="u'Lo volvemos a l...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=1L fecha='datetime.datetime...)'>,
             <Observacion 47L descripcion="u'La intervencion...'" grupo_de_resolucionID=2L
                    intervencionID=10L usuarioID=5L fecha='datetime.datetime...)'>]
        >>> len(intervencion.observaciones)
        4
        >>> obs = intervencion.observaciones[-1]
        >>> obs
            <Observacion 47L descripcion="u'La intervencion...'" grupo_de_resolucionID=2L
            intervencionID=10L usuarioID=5L fecha='datetime.datetime...)'>
        >>>

        @param intervencion: a la cual le queremos agregrar una observacion.
        @param descripcion: descripcion de la observacion.
        @param usuario: usuario que realiza la observacion.
        @param fecha: fecha de realizacion de la misma.
        @param grupo: grupo de resolucion logueado al momento de esta operacion

        @type intervencion: C{Intervencion}
        @type decripcion: C{Unicode}
        @type usuario: C{Usuario}
        @type fecha: C{datetime}
        @type grupo: C{GrupoDeResolucion}

        """

    def cambiar_estado_ticket(self, estado, usuario, intervencion):
        """Comprueba si es necesario cambiar el estado del ticket o no, y a
        cual estado debe ir el ticket. Dependiendo del estado que se encuentra
        la intervencion es el nuevo estado.

        >>> dic = {'Resuelta': 'Solucionado a la espera OK',
        ...                 'En espera por grupo': 'No Solucionado',
        ...                 'Trabajando': 'Abierto derivado',
        ...                 'Finalizada': 'No Solucionado'}
        >>> estado = 'Resuelta'
        >>> estado_ticket = dic.get(estado)
        >>> estado_ticket
        'Solucionado a la espera OK'
        >>>

        @param estado: estado de la intervencion.
        @param usuario: usuario que realizo el cambio.
        @param intervencion: es la que se esta modificando.

        @type estado: C{string}
        @type usuario: C{Usuario}
        @type intervencion: C{Intervencion}
        """


class Clasificacion:
    def __init__():
        pass

# Interfaz Mesa de Ayuda
class MesaDeAyudaGUI:
    """
    Grupo de Resolucion mesa de ayuda.

    Clase que se encargara de la parte grafica del actor mesa de ayuda. Es el
    I{unico} que puede abrir, derivar y cerrar ticket.

    """
    def __init__(self, usuario_logueado):
        """

        @param usuario_logueado: Usuario registrado en el sistema.
        @type usuario_logueado: C{lib.database.Usuario}
        """
    def put_user_and_date(self, user):
        """
        Muestra el usuario logueado, mostrando el nombre de usuario, apellido y
        nombre, asi como tambien el nombre del grupo de resolucion.
        
        >>> user = usuario.empleado.apellido + " " + usuario.empleado.nombre + " "
        >>> texto = ("Bienvenido:", user, 
        ...     ("Usuario: %s" % usuario.u_legajo),
        ...     ("Grupo de Resolucion:"),
        ...     ("Mesa de Ayuda"))
        >>> print "\n".join(texto)
        Bienvenido:
        Lichtenstein Tanya 
        Usuario: u56581
        Grupo de Resolucion:
        Mesa de Ayuda
        >>> 

        @param user: Apellido y nombre del usuario logueado en el sistema.
        @type user: C{string}
        """

    def obtener_numero_ticket(self):
        """Obetiene el 
        """
    def create_ticket(self, widget):
        """
        GUI crear ticket. Permite generar el dialogo de crear ticket CDU01

        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}

        """
    def my_ticket(self, widget):
        """
        Permite generar ... se me ocurrio que podiamos mostrar los ticket que
        fue generado en su sesion, ó todos lo anteriores

        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}
        """
    def close_sesion(self, widget):
        """
        Consulta por al usuario con un C{MensajeDeAdvertencia}, si realmente
        quiere abandonar la sesion.
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}
        """
    def close(self, widget):
        """
        Cierra la sesion y abandona el sistema.
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}

        """
    def about(self, widget):
        """
        Funcion invocada desde el Menu Acerca de: Despliega un C{MensajeDeAbout}. 
        """
    def find_ticket(self, widget):
        """GUI buscar ticket.

        Permite generar el dialogo de buscar ticket CDU02
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}

        """

# Clase Crear
class CreateTicket:
    """Crear ticket.

    Clase que permitira el manejo de la interfaz de creación de ticket.
    Utilizado en el CDU-01 Registrar Ticket.

    Requerimientos especiales:
        1. El registro del ticket deser ser agil y debe poder utilizarse con la
        sola utilizacion del teclado.
        2. La tecla Enter debe permitir navegar de campo en campo
     
    """
    def __init__(self, padre, usuario_logueado):
        """
        @param padre: Interfaz Mesa de Ayuda
        @param usuario_logueado: Usuario registrado en el sistema.
        @type padre: C{MesaDeAyudaGUI}
        @type usuario_logueado: C{lib.database.Usuario}
        """
    def conect_entry_enter(self):
        """
        Permite generar las señales para cumplir con el requisito especial I{2}
        del caso de uso.
        """
    def completar_campos(self):
        """
        Completara los campos de entrada.

        Busca en la base de datos el nombre y apellido del Empleado con legajo
        "nro_legajo" y la Clasificacion con "nro_clasificacion", y los muestro
        en los campos correspondientes luego de presionar <Enter> desde la
        funcion conect_entry_enter.

        """
    def datos_no_validos(self):
        """
        Valida los datos de entrada para CREAR TICKET. 
        Comprueba todos lo campos obligatorios necesarios para completar esta
        actividad, ellos son:
            - Legajo
            - Clasificacion
            - Descripcion del problema
        
        @return: (C{True}, error) si los datos no son validos, sino (C{False}, "")
        """
    def validate_create_ticket(self, widget):
        """
        Llama a la funcion C{datos_no_validos}

        Dependiendo de lo que retorna C{datos_no_validos} mostrara la informacion
        necesaria para la proxima actividad I{cerrar ticket} o  I{derivar
        ticket}

        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}
        """
    def close_ticket(self, widget):
        """
        CDU03 Cerrar ticket.

        Llama a C{observacion_valida}, dependiendo del retorno de esta funcion
        despliega un C{MensajeDeAdvertencia} de confirmacion para llevar a cabo
        esta accion. Si el usuario seleciona C{Si} Cerrara el ticket almacenando
        la fecha y hora actual. 
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}
        """
    def observacion_valida(self):
        """
        Valida el campo Observaciones.

        Este campo es un dato obligatorio, tanto para la derivacion como para
        el cierre de un reclamo.
        @return: C{(observacion, True)} si es valida y C{("", False)} en caso
        contrario       
        """
    def derivar_ticket(self, widget):
         """Deriva el ticket al grupo de resolucion que selecciona el usuario.

        Tenemos que validar observacion y ademas hacer hbox49 show() que ahí se
        encuentra la informacion de los grupos de resolucion. Datos necesarios
        para la derivacion de ticket.Llama a C{armar_lista_de_grupos}
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}
        """
    def armar_lista_de_grupos(self):
        """
        Permite completar el treeview31 con los grupos habilitados para
        resolver el problema del ticket. Consulto la BD y levanto todos los
        grupos que tengan asociados esa clasificacion.
         
        """
    def add_find_column(self, title, columnId):
        """Agrega una columna al la lista de grupos habilitados.

        @param title: Titulo de la columna
        @param columnId: posicion donde queremos la columna
        @type title: C{string}
        @type columnId: C{int}
        """
    def un_grupo_seleccionado(self):
        """
        Permite comprobar si selecciono un grupo de la lista.
        @return: C{(pos, True)} si se selecciono o C{(, False)}
        """
    def validate_derivar_ticket(self, widget):
        """
        Invoca a C{un_grupo_seleccionado}, en caso afirmativo deriva el ticket
        registrando el usuario y la fecha.
        @param widget:  Widget de mesa de ayuda
        @type widget: C{MesaDeAyudaGUI}

        """
# Mesa de Ayuda
class MesaDeAyuda(GrupoDeResolucion):
    def __init__(self, grupo):
        """
        Instanciamos el diccionario de tickets vacio, C{id:ticket} para ir
        guardando los ticket que se van generando en el transcurso de la
        sesion del usuario.

        @param grupo: Grupo de resolucion del usuario logueado en el sistema.
        @type grupo: C{lib.database.GrupoDeResolucion}
        """
    def crearTicket(self, usuario, empleado, clasificacion, descripcion,
            fecha_creacion):
        """Registra en la BD y agrega al diccionario el nuevo ticket.
        
        Crea una instancia de ticket para agregarla a la self.ticket y hace un
        set en la BD en la tabla Ticket.
                
        @param usuario: usuario que registro el ticket
        @param empleado: empleado solicitante del ticket
        @param clasificacion: clasificacion del problema actual
        @param descripcion: descripcion del problema
        @param fecha_creacion: fecha de creacion del ticket

        @type usuario: C{lib.database.Usuario}
        @type empleado: C{lib.database.Empleado}
        @type clasificacion: C{lib.database.Clasificacion}
        @type descripcion: C{string}
        @type fecha_creacion: C{datetime.datetime}
        @return: C{nuevo_ticket} ticket creado en este proceso.

        >>> tickets[ticket.id] = ticket
        >>> tickets
        {18: <Ticket 18 fecha_cierre=None
        fecha_creacion='datetime.datetime...)' descripcion=u'LO'
        grupo_de_resolucionID=1L empleado_solicitanteID=41L
        usuario_creacionID=1L usuario_cierreID=None cerrado=False>}
        >>> for historial in ticket.historial_de_estado:
        ...     print historial
        ...     print historial.estado.nombre
        ...
        <HistorialDeEstado 7 fecha='datetime.datetime...)' usuarioID=1L estadoID=1L ticketID=7L>
        Abierto en Mesa de Ayuda
        >>> 
        """
    def cerrarTicket(self, usuario_logueado, observacion, fecha_cierre, ticket):
        
        """Realiza el cierre del ticket.
        
        Actualiza la base de datos y elimina el ticket del diccionario 'tickets'
        del usuario mesa de ayuda.

        >>> ticket
        <Ticket 5 fecha_cierre=None fecha_creacion='datetime.datetime...)' descripcion="u'necesita agreag...'" grupo_de_resolucionID=1L empleado_solicitanteID=40L usuario_creacionID=1L usuario_cierreID=None cerrado=True>
        >>> for historial in ticket.historial_de_estado:
        ...     print historial
        ...     print historial.estado.nombre
        ...
        <HistorialDeEstado 4 fecha='datetime.datetime...)' usuarioID=1L estadoID=1L ticketID=5L>
        Abierto en Mesa de Ayuda
        <HistorialDeEstado 5 fecha='datetime.datetime...)' usuarioID=1L estadoID=4L ticketID=5L>
        Cerrado
        >>>

        @param usuario_logueado: usuario que realiza el cierre
        @param observacion: observacion de la intervencion
        @param fecha_cierre: fecha de cierre del ticket
        @param ticket: ticket del diccionario
        @type usuario_logueado: C{lib.database.Usuario}
        @type observacion: C{string}
        @type fecha_cierre: C{datetime.datetime}
        @type ticket: C{lib.database.Ticket}
        """
    def derivarTicket(self, grupo, fecha_derivacion, obs, usuario, ticket):
        """Realiza la derivacion del ticket.
        
        Actualiza la base de datos y elimina el ticket del diccionario 'tickets'
        del usuario mesa de ayuda.

        >>> ticket
        <Ticket 8 fecha_cierre=None fecha_creacion='datetime.datetime...)' descripcion="u'Descripcion del...'" grupo_de_resolucionID=3L empleado_solicitanteID=13L usuario_creacionID=1L usuario_cierreID=None cerrado=False>
        >>> for historial in ticket.historial_de_estado:
        ...     print historial
        ...     print historial.estado.nombre
        ...
        <HistorialDeEstado 9 fecha='datetime.datetime...)' usuarioID=1L estadoID=1L ticketID=8L>
        Abierto en Mesa de Ayuda
        <HistorialDeEstado 10 fecha='datetime.datetime...)' usuarioID=1L estadoID=2L ticketID=8L>
        Abierto derivado
        >>> ticket.grupo_de_resolucion
        <GrupoDeResolucion 3 estado=True fecha_creacion='datetime.datetime...)' descripcion="u'Resuelven probl...'" nombre=u'Servicio Tecnico'>
        >>> ticket.grupo_de_resolucion.nombre
        u'Servicio Tecnico'
        >>> 

        @param grupo: grupo de resolucion a derivar
        @param fecha_derivacion: fecha actual 
        @param obs: observacion de la intervencion
        @param usuario: usuario que realiza la derivacion
        @param ticket: ticket en el diccionario
        @type grupo: C{lib.database.GrupoDeResolucion}
        @type fecha_derivacion: C{datetime.datetime}
        @type obs: C{string}
        @type usuario: C{lib.database.Usuario}
        @type ticket: C{lib.database.Ticket}

        """
    def buscarTicket(self, empleado, ultimo_grupo, clasificacion, estado,
                 nro_ticket, fecha_apertura_desde, fecha_apertura_hasta,
                 fecha_ultimo_cambio_desde, fecha_ultimo_cambio_hasta):
        """Busca los tickets que cumplen con lo criterios.

        Recorrera el diccionario de tiket que tenemos en memoria y ira creando la
        'lista_ticket', luego consulta la BD para obtener mas informacion de
        ser necesaria, este resultado se agrega al diccionario que tenemos en
        memoria.

        @param empleado: empleado que realizo el reclamo
        @param ultimo_grupo: ultimo grupo asociado al ticket
        @param clasificacion: clasificacion del ticket 
        @param estado: estado actual de los ticket 
        @param nro_ticket: numero del ticket 
        @param fecha_apertura_desde: NN
        @param fecha_apertura_hasta: NN
        @param fecha_ultimo_cambio_desde: NN
        @param fecha_ultimo_cambio_hasta: NN


        @type empleado: C{lib.database.Empleado}
        @type ultimo_grupo: C{lib.database.GrupoDeResolucion}
        @type clasificacion: C{lib.database.Clasificacion}
        @type estado: C{lib.database.Estado}
        @type nro_ticket: C{int}
        @type fecha_apertura_desde: C{datetime.datetime}
        @type fecha_apertura_hasta: C{datetime.datetime}
        @type fecha_ultimo_cambio_desde: C{datetime.datetime}
        @type fecha_ultimo_cambio_hasta: C{datetime.datetime}

        @return: C{lista_ticket}
        """

# clase buscar ticket
class BuscarTicket:
    """Realiaza la actividad establecida en el CDU-02.

    Presenta la interfaz de los criterios de búsqueda de ticket.
    """
    def __init__(self, padre):
        """
        Se levanta el archivo .glade y se preparan las cabeceras 'titulos' de
        las columnas, para mostrar el resultado. Llama a C{armar_combos} y
        tambien a C{conect_entry_enter}
        @param padre: Interfaz Mesa de Ayuda
        @type padre: C{MesaDeAyudaGUI}
        """
    def conect_entry_enter(self):
        """
        Permite generar the activate signal para los widget asociados al
        empleado.
        """
    def completar_campos(self):
        """Completará los campos de apellido y nombre.

        Busca en la base de datos el nombre y apellido del Empleado con legajo
        "nro_legajo".

        """
    def armar_combos(self):
        """Llenara con los datos correspondientes los comboboxentry.

        Buscará en la base de datos los grupos de resolucion, las clasificaciones
        y los estados activos.

        """
    def add_find_column(self,title,columnId):
        """
            Esta funcion agrega una columna al resultado de la búsqueda
        """
    def datos_no_validos(self):
        """Valida los campos de fechas.

        @return: C{True} si la fecha de apertura o ultimo cambio es mayor a la
        actual, de lo contrario C{False}
        """
    def mostrar_resultados(self, widget):
        """
        Llamara a la funcion C{datos_no_validos} si retorna C{False} invocara a 
        C{buscarTicket} de C{MesaDeAyuda}

        Se mostraran todos los ticket que halla encontrado la funcion.
        """
    def tomar_valor_combo(self, combo):
        """Devuelve el valor del combo requerido.

        Retorna el valor del diccionario 'combo' que tenga como llave
        el valor de seleccion del 'combo'.
            1. Grupo de resolucion
            2. Clasificacion
            3. Estado
            
        >>> diccionario = {1: ['Grupo Uno', 'Grupo Dos'],
        ...             2: ['Clasificacion 1', 'Clasificacion 2'],
        ...             3: ['Estado 1', 'Estado 2']}
        >>> combo = 1
        >>> diccionario[combo][1]
        'Grupo Dos'
        >>> combo = 2
        >>> diccionario[combo][1]
        'Clasificacion 2'

        @param combo: valor del combo requerido
        @type combo: C{int}

        """
    def close(self,widget):
        """Cancelacion de la operación.

        Se mostrara un mensaje de retroalimentacion de advertencia, para
        consultar al usuario si realmente es lo que desea.
        """
    def limpiar_campos(self,widget):
        """Limpiara los campos.

        Recorrera todos los widget de 'criterios de busqueda' y los pondra en
        su estado de default.
        Llama a la funcion C{cleane_spin} para setear en default los
        'spinButton'
        """
    def cleane_spin(self):
        """Pone los spin button en sus valores de default."""
    
    def derivar_ticket(self,widget):
        """
        Permitira invocar a la clase C{DerivarTicket} para que se despliegue el
        dialog de derivacion de ticket.

        """
    def cerrar_ticket(self, widget):
        """
        Permitira invocar a la clase C{CerrarTicket} para que se despliegue el
        dialog de cierre de ticket.
        """
    def detalle_del_ticket(self, widget):
        """
        Permitira invocar a la clase C{DetalleDelTicket} para mostrar al usuario
        le historico del ticket.
        """
    def configurar_reporte(self, widget):
        """
        Permitira seleccionar la forma de presentacion para la impresion.
        """
#clase Detalle ticket
class DetalleDelTicket:
    """
    Permitira desplegar el detalle del ticket
    """
    def __init__(self, padre, ticket):
        """
        Terminar
        """
# clase Cerrar ticket
class CerrarTicket:
    def __init__(self, padre, ticket):
        """

        @param padre: Interfaz Buscar Ticket
        @param ticket: Ticket para cerrar
        @type padre: C{BuscarTicket}
        @type ticket: C{lib.database.Ticket}
        """
    def datos_validos(self):
        """
        >>> def datos_validos():
        ...     if 'observacion':
        ...             return 'observacion', True
        ...     else:
        ...             return '',False
        ...
        >>> obs, bandera = datos_validos()
        >>> if bandera:
        ...     print 'Datos validos'
        ...
        Datos validos
        >>>

        Comprueba que el campo obligatorio C{Observaciones} este completo.
        @return: C{(observacion,True)} en caso verdadero.
        """
    def cerrar_ticket(self, widget):
        """
        Invoca a la funcion C{datos_validos}, dependiendo del valor de retorno
        de esa funcion llama a C{cerrarTicket} de la clase C{MesaDeAyuda}
        """
    def close(self,widget):
        """Cancelacion de la operacion.

        Se mostrará un mensaje de retroalimentación de advertencia, para
        consultar al usuario si realmente es lo que desea.
        """
# Derivar ticket
class DerivarTicket:
    def __init__(self, padre, ticket):
        """
        Invoca a la funcion C{self.datos_iniciales()} y C{self.armar_combos()},
        para completar de armar la interfaz de manera correcta.

        @param padre: Interfaz Buscar Ticket
        @param ticket: Ticket para cerrar
        @type padre: C{BuscarTicket}
        @type ticket: C{lib.database.Ticket}

        """
    def reclasificar(self, widget):
       """
       Dependiendo de la activacion del chekbox asociado a las clasificaciones,
       necesitamos armar el I{ComboBox} de clasificaciones, esta llamara a la
       funcion C{limpiar_combo_grupos} para limpiar el combo y completarlo
       nuevamente solo con los grupos de resolucion asociados a la
       clasificacion activada.
       """
    def rearmar_combo_grupo(self, widget):
        """
        Es activada cuando el comboBox de clasificaciones cambia de valor.

        Invova a la funcion C{limpiar_combo_grupos}, luego invoca a la funcion
        C{tomar_valor_combo} y dependiendo del valor de retorno de esa
        clasificacion, completa con los grupos de resolucion asociados a la
        clasificacion.

        """
    def limpiar_combo_grupos(self):
        """
        Elimina los datos del C{combo_grupo}
        """
    def datos_iniciales(self):
        """
        Setea los datos estaticos de la interfaz:
            1. Estado actual de ticket.
            2.  Descripcion del problema.
            3.  Nuevo estado. 
        """
    def armar_combos(self):
        """Llenara con los datos correspondientes los combobox.

        Buscara en la base de datos los grupos de resolucion y las clasificaciones
        
        """
    def derivar_ticket(self, ticket):
        """
        Invoca a C{datos_validos}, dependiendo del valor de retorno deriva el
        ticket o no. Solo hay que tener en cuenta que si la clasificacion es
        distinta a la del ticket, la agregamos al historial, sino solo llamamos
        a C{derivarTicket} de la clase C{MesaDeAyuda}
        """
    def tomar_valor_combo(self, combo):
        """Devuelve el valor del combo requerido.

        Retorna el valor del diccionario 'combo' que tenga como llave
        el valor de seleccion del 'combo'.
            1. Grupo de resolucion
            2. Clasificacion
            
        >>> diccionario = {1: ['Grupo Uno', 'Grupo Dos'],
        ...             2: ['Clasificacion 1', 'Clasificacion 2']}
        >>> combo = 1
        >>> diccionario[combo][1]
        'Grupo Dos'
        >>> combo = 2
        >>> diccionario[combo][1]
        'Clasificacion 2'

        @param combo: valor del combo requerido
        @type combo: C{int}

        """
    def close(self,widget):
        """Cancelacion de la operacion.

        Se mostrara un mensaje de retroalimentacion de advertencia, para
        consultar al usuario si realmente es lo que desea.
        """

if __name__=="__main__":
    import doctest
    doctest.testmod()
